package com.wind.utils;

import com.sun.management.OperatingSystemMXBean;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.Util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *     系统资源工具类
 * </p>
 * @author wind
 * @date    2024-12-10 10:57
 * @version v1.0
 */
public class SystemUtil {


    private SystemUtil(){
        
    }

    /**
     * 判断系统
     * @return
     */
    private static boolean isWindow(){
        String name = System.getProperty("os.name");
        if(name == null){
            return false;
        }
        return name.toLowerCase().contains("windows") || name.toLowerCase().contains("win");
    }

    /**
     * 获取系统信息， 操作系统， cpu， 内存， 磁盘
     */
    public static void getMetric(){
        // 创建 SystemInfo 对象
        SystemInfo si = new SystemInfo();
        // 获取操作系统信息
        OperatingSystem os = si.getOperatingSystem();
        System.out.println("操作系统: " + os.getFamily() + " " + os.getVersionInfo());
        // 获取 CPU 信息
        CentralProcessor processor = si.getHardware().getProcessor();
        System.out.println("CPU: " + processor.getProcessorIdentifier().getName());
        System.out.println("CPU 核心数: " + processor.getLogicalProcessorCount());
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        Util.sleep(1000); // 等待一段时间，比如1秒
        // 计算CPU使用率
        double cpuUsage = processor.getSystemCpuLoadBetweenTicks(prevTicks) * 100;
        System.out.println("CPU使用率：" + cpuUsage + "%");
        // 获取内存信息
        GlobalMemory memory = si.getHardware().getMemory();
        System.out.println("总内存: " + memory.getTotal() / 1024 / 1024 + " MB");
        System.out.println("可用内存: " + memory.getAvailable() / 1024 / 1024 + " MB");
        // 获取磁盘空间信息
        for (OSFileStore fs : si.getOperatingSystem().getFileSystem().getFileStores()) {
            System.out.println("磁盘: " + fs.getMount() + " 总空间: " + fs.getTotalSpace() / 1024 / 1024 + " MB" + " 剩余空间: " + fs.getFreeSpace() / 1024 / 1024 + " MB");
        }
    }

    /**
     * 获取系统内存，总内存，剩余内存
     * 返回list列表，元素1表示总内存，元素2表示空闲内存，单位kb
     * @return
     */
    public static List<Long> getMemory(){
        List<Long> result = new ArrayList<>();
        long total = 0L;
        long free = 0L;
        if(isWindow()){
            // 单位b
            OperatingSystemMXBean os = (OperatingSystemMXBean) ManagementFactory
                    .getOperatingSystemMXBean();
            // 总的物理内存+虚拟内存, 单位b转换成kb
            total = os.getTotalPhysicalMemorySize()/1024;
            // 剩余的物理内存, 单位b转换成kb
            free = os.getFreePhysicalMemorySize()/1024;
        }else{
            // kb
            try (BufferedReader reader = new BufferedReader(new FileReader("/proc/meminfo"))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.startsWith("MemTotal:")) {
                        String[] parts = line.split("\\s+");
                        total = Long.parseLong(parts[1]);
                    } else if (line.startsWith("MemFree:")) {
                        String[] parts = line.split("\\s+");
                        free = Long.parseLong(parts[1]);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        result.add(total);
        result.add(free);
        return result;
    }

    /**
     * 获取cpu
     * @return
     */
    public static List<String> getCpu(){
        List<String> result = new ArrayList<>();
        OperatingSystemMXBean osBean = (OperatingSystemMXBean) ManagementFactory
                .getOperatingSystemMXBean();
        double systemCpuLoad = osBean.getSystemCpuLoad() * 100;
        double processCpuLoad = osBean.getProcessCpuLoad();
        long availableProcessors = osBean.getAvailableProcessors();
        result.add(String.valueOf(availableProcessors));
        result.add(String.valueOf(systemCpuLoad));
        result.add(String.valueOf(processCpuLoad));
        return result;
    }

    /**
     * 获取系统磁盘，总磁盘，剩余磁盘
     * 文件系统, 总大小, 已使用, 可用, 使用率, 挂载点
     * @return
     */
    public static List<List<String>> getDisk(){
        List<List<String>> result = new ArrayList<>();
        if(isWindow()){
            for (char c = 'A'; c <= 'Z'; c++) {
                String dirName = c + ":/";
                File win = new File(dirName);
                if (win.exists()) {
                    List<String> ele = new ArrayList<>();
                    long total = win.getTotalSpace();
                    long free = win.getFreeSpace();
                    long use = total - free;
                    if(use < 0){
                        continue;
                    }
                    ele.add(String.valueOf(c));
                    ele.add(String.valueOf(total));
                    ele.add(String.valueOf(use));
                    ele.add(String.valueOf(free));
                    BigDecimal totalBd = new BigDecimal(String.valueOf(total));
                    BigDecimal useBd = new BigDecimal(String.valueOf(use));
                    String rate = useBd.divide(totalBd, 2, RoundingMode.HALF_UP).toString();
                    ele.add(rate);
                    ele.add("");
                    result.add(ele);
                }
            }
        }else{
            List<List<String>> lists = ProcessUtil.exec("df");
            if(!lists.isEmpty()){
                List<String> list = lists.get(0);
                int count = 0;
                for (String line : list) {
                    count++;
                    if(count == 1){
                        continue;
                    }
                    List<String> ele = new ArrayList<>();
                    String[] values = line.split("\\s+");
                    //文件系统, 总大小, 已使用, 可用, 使用率, 挂载点
                    ele.add(values[0]);
                    ele.add(values[1]);
                    ele.add(values[2]);
                    ele.add(values[3]);
                    String rate = values[4];
                    rate = rate.substring(0, rate.length() - 1);
                    BigDecimal rateBd = new BigDecimal(rate);
                    ele.add(rateBd.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP).toString());
                    ele.add(values[5]);
                    result.add(ele);
                }
            }
        }
        return result;
    }
}
